﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace GameLoop
{   /// <summary>
    /// The main class to implement the game loop. 
    /// </summary>
    public class FastLoop
    {
        PreciseTimer _timer = new PreciseTimer();
        /// <summary>
        /// The delegate loop call back representint the GameLoop() Method. 
        /// </summary>
        public delegate void LoopCallback(double elapsedTime);
        /// <summary>
        /// The loop call back representint the GameLoop() Method. 
        /// </summary>
        LoopCallback callBack;
        /// <summary>
        /// Will get the Method GameLoop.Program.GameLoop as 
        /// argument to be executed when the application enters
        /// idle mode. 
        /// </summary>
        public FastLoop(LoopCallback callback)
        {
            callBack = callback;
            Application.Idle += new EventHandler(OnApplicationEnterIddle);
        }
        /// <summary>
        //Is a listener that will be called when 
        // the application enters idle state. 
        //It will render the 
        /// </summary>
        void OnApplicationEnterIddle(object sender, EventArgs e)
        {
            while (IsAppStillIdle())
            {
                callBack(_timer.GetElapsedTime());
            }
        }
        /// <summary>
        ///Check with help of the C function PeekMessage if
        ///the App is in idle state. 
        /// </summary>

        private bool IsAppStillIdle()
        {
            Message msg;
            return !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
        }
        /// <summary>
        /// Message Structure that should be filled 
        ///by the C PeekMessage function.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct Message
        {
            public IntPtr hWnd;
            public Int32 msg;
            public IntPtr wParam;
            public IntPtr lParam;
            public int time;
            public System.Drawing.Point p;
        }
        /// <summary>
        ///Inport the C function from the User32.dll.
        ///Determines if there are any messages waiting in 
        ///the application’s event queue.
        /// </summary>
        [System.Security.SuppressUnmanagedCodeSecurity]
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern bool PeekMessage(
            out Message msg,
            IntPtr hWnd,
            uint messageFiltermin,
            uint messageFilterMax,
            uint flags);
    }
}
